package com.example.springboot2.service;

import com.example.springboot2.common.PageResult;
import com.example.springboot2.entity.Coupon;
import com.example.springboot2.entity.Merchant;
import com.example.springboot2.exception.BusinessException;
import com.example.springboot2.repository.CouponRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import jakarta.persistence.criteria.Predicate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * 优惠券服务类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CouponService {

    private final CouponRepository couponRepository;
    private final MerchantService merchantService;

    /**
     * 根据ID查找优惠券
     */
    public Coupon findById(Long id) {
        return couponRepository.findById(id)
                .orElseThrow(() -> new BusinessException("优惠券不存在"));
    }

    /**
     * 分页查询优惠券列表
     */
    public PageResult<Coupon> getCouponList(Long userId, Integer current, Integer size, 
                                            String name, String status, String couponType) {
        Merchant merchant = merchantService.getMerchantInfo(userId);
        
        Pageable pageable = PageRequest.of(current - 1, size, 
                Sort.by(Sort.Direction.DESC, "createdTime"));
        
        Specification<Coupon> spec = (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            
            // 商家条件
            predicates.add(criteriaBuilder.equal(root.get("merchant"), merchant));
            
            // 优惠券名称模糊查询
            if (StringUtils.hasText(name)) {
                predicates.add(criteriaBuilder.like(root.get("name"), "%" + name + "%"));
            }
            
            // 状态查询
            if (StringUtils.hasText(status)) {
                predicates.add(criteriaBuilder.equal(root.get("status"), Coupon.CouponStatus.valueOf(status)));
            }
            
            // 类型查询
            if (StringUtils.hasText(couponType)) {
                predicates.add(criteriaBuilder.equal(root.get("couponType"), Coupon.CouponType.valueOf(couponType)));
            }
            
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
        
        Page<Coupon> page = couponRepository.findAll(spec, pageable);
        return PageResult.of(page);
    }

    /**
     * 获取优惠券详情
     */
    public Coupon getCouponDetail(Long userId, Long couponId) {
        Merchant merchant = merchantService.getMerchantInfo(userId);
        Coupon coupon = findById(couponId);
        
        // 验证优惠券是否属于当前商家
        if (!coupon.getMerchant().getId().equals(merchant.getId())) {
            throw new BusinessException("无权访问该优惠券");
        }
        
        return coupon;
    }

    /**
     * 创建优惠券
     */
    @Transactional
    public Coupon createCoupon(Long userId, Coupon coupon) {
        Merchant merchant = merchantService.getMerchantInfo(userId);
        coupon.setMerchant(merchant);
        
        // 验证优惠券时间
        if (coupon.getStartTime().isAfter(coupon.getEndTime())) {
            throw new BusinessException("开始时间不能晚于结束时间");
        }
        
        // 设置初始状态
        coupon.setStatus(Coupon.CouponStatus.DRAFT);
        coupon.setUsedQuantity(0);
        
        Coupon savedCoupon = couponRepository.save(coupon);
        log.info("商家创建优惠券: {} - {}", merchant.getShopName(), coupon.getName());
        return savedCoupon;
    }

    /**
     * 更新优惠券
     */
    @Transactional
    public Coupon updateCoupon(Long userId, Long couponId, Coupon couponInfo) {
        Coupon existingCoupon = getCouponDetail(userId, couponId);
        
        // 检查优惠券状态是否允许修改
        if (existingCoupon.getStatus() == Coupon.CouponStatus.ONGOING || 
            existingCoupon.getStatus() == Coupon.CouponStatus.FINISHED) {
            throw new BusinessException("进行中或已结束的优惠券不允许修改");
        }
        
        // 更新优惠券信息
        existingCoupon.setName(couponInfo.getName());
        existingCoupon.setDescription(couponInfo.getDescription());
        existingCoupon.setCouponType(couponInfo.getCouponType());
        existingCoupon.setDiscountValue(couponInfo.getDiscountValue());
        existingCoupon.setMinAmount(couponInfo.getMinAmount());
        existingCoupon.setMaxDiscount(couponInfo.getMaxDiscount());
        existingCoupon.setTotalQuantity(couponInfo.getTotalQuantity());
        existingCoupon.setPerUserLimit(couponInfo.getPerUserLimit());
        existingCoupon.setStartTime(couponInfo.getStartTime());
        existingCoupon.setEndTime(couponInfo.getEndTime());
        existingCoupon.setApplicableGoodsIds(couponInfo.getApplicableGoodsIds());
        existingCoupon.setApplicableCategories(couponInfo.getApplicableCategories());
        existingCoupon.setIsNewUserOnly(couponInfo.getIsNewUserOnly());
        
        // 验证优惠券时间
        if (existingCoupon.getStartTime().isAfter(existingCoupon.getEndTime())) {
            throw new BusinessException("开始时间不能晚于结束时间");
        }
        
        Coupon savedCoupon = couponRepository.save(existingCoupon);
        log.info("商家更新优惠券: {} - {}", existingCoupon.getMerchant().getShopName(), couponInfo.getName());
        return savedCoupon;
    }

    /**
     * 删除优惠券
     */
    @Transactional
    public void deleteCoupon(Long userId, Long couponId) {
        Coupon coupon = getCouponDetail(userId, couponId);
        
        // 检查优惠券状态是否允许删除
        if (coupon.getStatus() == Coupon.CouponStatus.ONGOING) {
            throw new BusinessException("进行中的优惠券不允许删除");
        }
        
        couponRepository.delete(coupon);
        log.info("商家删除优惠券: {} - {}", coupon.getMerchant().getShopName(), coupon.getName());
    }

    /**
     * 批量删除优惠券
     */
    @Transactional
    public void batchDeleteCoupons(Long userId, List<Long> couponIds) {
        for (Long couponId : couponIds) {
            deleteCoupon(userId, couponId);
        }
        
        Merchant merchant = merchantService.getMerchantInfo(userId);
        log.info("商家批量删除优惠券: {} - 数量: {}", merchant.getShopName(), couponIds.size());
    }

    /**
     * 更新优惠券状态
     */
    @Transactional
    public void updateCouponStatus(Long userId, Long couponId, Coupon.CouponStatus status) {
        Coupon coupon = getCouponDetail(userId, couponId);
        
        // 验证状态转换的合法性
        validateStatusTransition(coupon.getStatus(), status);
        
        coupon.setStatus(status);
        couponRepository.save(coupon);
        
        log.info("商家更新优惠券状态: {} - {} - {}", 
                coupon.getMerchant().getShopName(), coupon.getName(), status);
    }

    /**
     * 批量更新优惠券状态
     */
    @Transactional
    public void batchUpdateCouponStatus(Long userId, List<Long> couponIds, Coupon.CouponStatus status) {
        for (Long couponId : couponIds) {
            updateCouponStatus(userId, couponId, status);
        }
        
        Merchant merchant = merchantService.getMerchantInfo(userId);
        log.info("商家批量更新优惠券状态: {} - 数量: {} - 状态: {}", 
                merchant.getShopName(), couponIds.size(), status);
    }

    /**
     * 获取优惠券统计数据
     */
    public CouponStats getCouponStats(Long userId) {
        Merchant merchant = merchantService.getMerchantInfo(userId);
        
        long totalCount = couponRepository.countByMerchant(merchant);
        long draftCount = couponRepository.countByMerchantAndStatus(merchant, Coupon.CouponStatus.DRAFT);
        long ongoingCount = couponRepository.countByMerchantAndStatus(merchant, Coupon.CouponStatus.ONGOING);
        long finishedCount = couponRepository.countByMerchantAndStatus(merchant, Coupon.CouponStatus.FINISHED);
        
        return CouponStats.builder()
                .totalCount(totalCount)
                .draftCount(draftCount)
                .ongoingCount(ongoingCount)
                .finishedCount(finishedCount)
                .build();
    }

    /**
     * 获取有效优惠券
     */
    public List<Coupon> getValidCoupons(Long userId) {
        Merchant merchant = merchantService.getMerchantInfo(userId);
        return couponRepository.findValidCouponsByMerchant(merchant, LocalDateTime.now());
    }

    /**
     * 验证状态转换的合法性
     */
    private void validateStatusTransition(Coupon.CouponStatus currentStatus, Coupon.CouponStatus newStatus) {
        // 这里可以添加状态转换的业务规则
        if (currentStatus == Coupon.CouponStatus.FINISHED && newStatus != Coupon.CouponStatus.INVALID) {
            throw new BusinessException("已结束的优惠券只能设置为失效状态");
        }
    }

    /**
     * 优惠券统计数据DTO
     */
    @lombok.Data
    @lombok.Builder
    public static class CouponStats {
        private Long totalCount;
        private Long draftCount;
        private Long ongoingCount;
        private Long finishedCount;
    }
}
